package sg.edu.nus.iss.phoenix.schedule.service;

import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.TreeMap;

import sg.edu.nus.iss.phoenix.authenticate.dao.impl.UserDaoImpl;
import sg.edu.nus.iss.phoenix.authenticate.entity.User;
import sg.edu.nus.iss.phoenix.core.dao.DAOFactoryImpl;
import sg.edu.nus.iss.phoenix.core.exceptions.NotFoundException;
import sg.edu.nus.iss.phoenix.radioprogram.dao.impl.RadioProgramDAOImpl;
import sg.edu.nus.iss.phoenix.radioprogram.entity.RadioProgram;
import sg.edu.nus.iss.phoenix.schedule.dao.ScheduleDAO;
import sg.edu.nus.iss.phoenix.schedule.entity.Schedule;
import sg.edu.nus.iss.phoenix.utils.DateHolder;
/**
 * Schedule Service provides the Access to Schedule DAO 
 * 
 * @author Low  Kheng Hian (A0092668N)
 * @author Nang Sai Hom (A0092617B)
 *  
 * @version 1.0 2012/9/27
 */
public class ScheduleService {
	DAOFactoryImpl factory;
	ScheduleDAO scheduleDao;

	/**
	 * This method allows for the construction of a new instance of the DAO Factory implementation array.
	 * It then equates the data array to the schedule DAO. 
	 */
	public ScheduleService() {
		factory = new DAOFactoryImpl();
		scheduleDao = factory.getScheduleDAO();
	}
	/** 
	 * This method allows the insertion of schedule to the existing DAO of schedule.	
	 * @param schedule
	 */
	public void insertScehdule(Schedule schedule) {
		try {
			scheduleDao.create(schedule);
		} catch (SQLException e) {
			e.printStackTrace();
		}

	}
/**
	 * This method allows the updating of the schedule from the existing DAO of the schedule.
	 * @param schedule
	 */
	public void updateScehdule(Schedule schedule) {
		try {
			scheduleDao.save(schedule);
		} catch (NotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}

	}

	/**
	 * This method allows the deletion of the schedule from the existing DAO of the schedule.
	 * @param schedule
	 */
	public void deleteScehdule(Schedule schedule) {
		try {
			scheduleDao.delete(schedule);
		} catch (NotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}

	}
/**
	 * This method accesses the schedule arraylist and finds all schedule that is available.
	 * @return current all schedule array list.
	 */
	public ArrayList<Schedule> findAllSchedule() {
		ArrayList<Schedule> currentList = new ArrayList<Schedule>();
		try {
			currentList = (ArrayList<Schedule>) scheduleDao.loadAll();
			// System.out.println(currentList);
			for (Schedule sch : currentList) {
				loadScheduleDetails(sch);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return currentList;
	}
/**
	 * This method accesses the schedule arraylist and finds all schedule filtered by date.
	 * @param date
	 * @return current all schedule array list filtered by date.
	 */
	public ArrayList<Schedule> findAllSchedule(Date date) {
		ArrayList<Schedule> currentList = new ArrayList<Schedule>();
		try {
			currentList = (ArrayList<Schedule>) scheduleDao.loadAll(date);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return currentList;
	}
/**
	 * This method copies a copy of the schedule intended.
	 * @param schedule
	 * @return new schedule.
	 */
	public Schedule copySchedule(Schedule schedule) {
		Schedule newSchedule = new Schedule();
		try {
			newSchedule.setProgram(schedule.getProgram());
			newSchedule.setStartDate(schedule.getStartDate());
			newSchedule.setEndDate(schedule.getEndDate());
			newSchedule.setPresenter(schedule.getPresenter());
			newSchedule.setProducer(schedule.getProducer());		
			scheduleDao.create(newSchedule);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return newSchedule;
	}
/**
	 * This method loads the intended schedule.
	 * @param schedule
	 * @return intended schedule
	 */
	public Schedule loadSchedule(Schedule schedule) {
		try {
			Schedule sch = scheduleDao.load(schedule);
		    loadScheduleDetails(schedule);
			return sch;
		} catch (NotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return null;
	}
	/**
	 * This method sets the schedule details based on the schedule entered.
	 * @param input schedule
	 * @throws SQLException
	 */
	private void loadScheduleDetails(Schedule sch) throws SQLException{
		UserDaoImpl userDao = new UserDaoImpl();

		// only user_id is returned from scheduleDao. Load all user
		// details
		User presenter = new User();
		try {
			userDao = new UserDaoImpl();
			presenter = userDao.getObject(sch.getPresenter().getId());
		} catch (NotFoundException e) {
			e.printStackTrace();
		}
		sch.setPresenter(presenter);

		User producer = new User();
		try {
			userDao = new UserDaoImpl();
			// System.out.println("producer " + sch.getProducer());
			producer = userDao.getObject(sch.getProducer().getId());
		} catch (NotFoundException e) {
			e.printStackTrace();
		}
		sch.setProducer(producer);

		RadioProgramDAOImpl proDao = new RadioProgramDAOImpl();

		RadioProgram program = new RadioProgram();

		try {
			program = proDao
					.getObject(sch.getProgram().getProgram_id());
		} catch (NotFoundException e) {
			e.printStackTrace();
		}

		sch.setProgram(program);
		
	}
	/**
	 * This treemap allows for mapping of the slots to the date intended.
	 * @param date
	 * @return tree
	 */
	public TreeMap<Integer, DateHolder> findAvailableSlots(Date date) {
		ArrayList<Schedule> schedules = this.findAllSchedule(date); 
		HashMap<Integer, DateHolder> slots = new HashMap<Integer,DateHolder>();
				
		for(int i=0; i< 24; i++){
			Date d1 = new Date(date.getYear(), date.getMonth(), date.getDate(), i, 0,0);
			Date d2= new Date(date.getYear(), date.getMonth(), date.getDate(), i+1,0,0);
			String start = new SimpleDateFormat("yyyy-MM-d HH:mm:ss").format(d1);
			String end = new SimpleDateFormat("yyyy-MM-d HH:mm:ss").format(d2);
			DateHolder dh = new DateHolder(0, start, end);			
			slots.put(i, dh);
		}
//		int i=0;
		for(Schedule schedule : schedules){
		   Date date1 = schedule.getStartDate();
		   int hour = date1.getHours(); 
		   DateHolder dh1 = slots.get(hour);
		   dh1.setStatus(1);
		   slots.put(hour, dh1);
		   
		}
		
		TreeMap<Integer, DateHolder> tree = new TreeMap<Integer, DateHolder>();
		tree.putAll(slots);
		return tree;
	}

}


